#pragma once

#include "CurrentThread.h"
#include "IOUring.h"
#include "Noncopyable.h"
#include <atomic>
#include <mutex>

class IOUringEventLoop : public Noncopyable {
  public:
    using Functor = std::function<void()>;
    using NewConnectionCallback = std::function<void(struct io_uring_cqe *cqe)>;
    using WriteCompleteCallback = std::function<void(struct io_uring_cqe *cqe)>;
    using ReadCompleteCallback = std::function<void(struct io_uring_cqe *cqe)>;

    IOUringEventLoop(int acceptFd);
    IOUring *ioUring() { return &iouring_; }
    void loop();
    void quit() { quit_ = true; }
    void runInLoop(Functor cb); // 在当前loop中执行
    void queueInLoop(Functor cb); // 把cb放入loop,唤醒loop所在的线程，执行cb

    bool isInLoopThread() const { return threadId_ == CurrentThread::tid(); }

    void addAccept(int fd, unsigned flags) {
        iouring_.addAccept(fd, peerAddr_, flags);
    }
    void tryAddAccept(int fd, unsigned flags) {
        if (!hasPrepAccept_.exchange(true)) {
            addAccept(fd, flags);
        }
    }
    void addProvideBuf(uint16_t bid) { iouring_.addProvideBuf(bid); }
    void addProvideBufAll() { iouring_.addProvideBufAll(); }
    void addRead(int fd, size_t size, uint32_t flags) {
        iouring_.addRead(fd, size, flags);
    }
    void addWrite(int fd, uint16_t bid, size_t size, uint32_t flags) {
        iouring_.addWrite(fd, bid, size, flags);
    }
    void setNewConnectionCallback(NewConnectionCallback cb) {
        iouring_.setNewConnectionCallback(cb);
    }
    void setWriteCompleteCallback(WriteCompleteCallback cb) {
        iouring_.setWriteCompleteCallback(cb);
    }
    void setReadCompleteCallback(ReadCompleteCallback cb) {
        iouring_.setReadCompleteCallback(cb);
    }

  private:
    void doPendingFunctors();

  public:
    std::atomic_bool hasPrepAccept_;
    int acceptFd_;
    InetAddress peerAddr_;

  private:
    IOUring iouring_;
    std::atomic_bool looping_;
    std::atomic_bool quit_;
    const pid_t threadId_;
    std::atomic_bool callingPendingFunctors_;
    std::vector<Functor> pendingFunctors_; // 存储loop需要执行的所有回调操作
    std::mutex mutex_;                     // 保护vector的线程安全
};                                         // class IOUringEventLoop
